/**
 * @fileoverview Class declarations:
 *    - shortcuts
 *    - processors
 *
 */

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

/**
 * class method index
 */
Dx.Class.methods = {};

/**
 * class method identifier seed used to generate method ids.
 */
Dx.Class.methodIdGen = 0;

/**
 * Creates a Dx constructor and becomes base constructor of all Dx subclasses
 * @this {Object} instance of Dx Class
 * @return {Function} synthesized Dx Constructor.
 */
Dx.Class.createConstructor = function() {

   function Constructor() {

      var Class = arguments.callee;

      var me = this;

      if (!(me instanceof Class)) {

         me = Dx.createObject(Class);

      }

      me.__construct.apply(me, arguments);

      return me;

   };

   Constructor.isDxSynthesized = true;

   return Constructor;

};

/**
 * Checks if methodName exists as custom method for o instance
 * @param {String} methodName the method name to find.
 * @param {Object} o the instance to inspect.
 * @return {Boolean} true if found and false if doesnt exist.
 */
Dx.Class.isMethodOf = function(methodName, o) {

   var D = Dx;

   return D.isPropertyEnumerable(methodName, o) &&

      D.isFunction(o[methodName]);

};


////////////////////////////////////////////////////////////////////////
// Helpers: supplement
////////////////////////////////////////////////////////////////////////

/**
 * supplement for Class creation
 */
Dx.Class.supplement = {

/**
 * registers Function to class method factory which will be used for calling
 *    this.$super() and this.$overridden() methods
 * @param {Function} fn the Function to register
 * @return {String} the unique identifier of the method
 */
   'registerMethod': function(fn) {

      var D = Dx;

      var DClass = D.Class;

      var list = DClass.methods;

      var id = fn.$mid;

      if (!id) {

         // generate id
         id = 'm' + (++DClass.methodIdGen);

         fn.$mid = id;

         list[id] = fn;

      }

      return id;

   },

/**
 * Applies class property to Dx based class
 * @private
 * @this {Object} superclass prototype
 * @param {String} name property name
 * @param {*} value property value
 * @param {Object} properties all properties to be synthesized
 */
   '_callback_synthesizeClassProperty': function(name, value, properties) {

      var D = Dx;

      var DClass = D.Class;

      if (properties.hasOwnProperty(name)) {

         if (D.isFunction(value) && DClass.isMethodOf(name, this)) {

            // register superclass method
            value.$parent = DClass.supplement.registerMethod(this[name]);

         }

         this[name] = value;

      }

   },

/**
 * Applies overridden class property to Dx based class
 * @private
 * @this {Object} superclass prototype
 * @param {String} name property name
 * @param {*} value property value
 * @param {Object} properties all properties that overrides the prototype
 */
   '_callback_synthesizeOverrideProperty': function(name, value, properties) {

      var D = Dx;

      var DClass = D.Class;

      var S = DClass.supplement;

      var methodList, overriden_mid, old_method, old_mid, parent_mid;

      if (properties.hasOwnProperty(name)) {

         // do not override constructor!
         if (name == 'constructor') {

            name = '__construct';

         }

         if (D.isFunction(value)) {

            methodList = DClass.methods;

            if (DClass.isMethodOf(name, this)) {

               // check if superclass
               old_method = this[name];

               old_mid = old_method.$mid;

               parent_mid = old_method.$parent;

               // if registered, replace
               if (old_mid) {

                  methodList[old_mid] = value;

                  value.$mid = old_mid;

                  delete old_method.$mid;

               }

               // register overridden method
               value.$overridden = S.registerMethod(old_method);

               // copy old values
               if (parent_mid) {

                  value.$parent = parent_mid;

               }

            }

         }

         this[name] = value;

      }

   },

/**
 *  recursively creates a callback from the cascaded Class inheritance chain.
 *  @param {String} path the path of the class declaration
 *  @param {String} tag the call tag used to categorize the callback
 *  @param {String} callbackName the callback name defined in the class
 *    declaration definition without the &#64;&#64; prefix.
 *    (e.g. "precallback" instead of "&#64;&#64;precallback")
 */
   'applyRecursiveCallback': function(path, tag, callbackName) {

      var D = Dx;

      var DClass = D.Class;

      var chain = DClass.getDeclarationPathChain(path);

      var definitionName = '@@' + callbackName;

      for (var definition, callback, l = chain.length; l--;) {

         definition = chain[l].definition;

         if (definition.hasOwnProperty(definitionName) &&

            D.isFunction(callback = definition[definitionName])

         ) {

            DClass.setCallback(path, tag, callback);

         }

      }

   },

/**
 * Superclass method caller for all Dx subclasses
 * @this {Object} instance of Dx Class
 * @return {*} returned value from superclass method call.
 */
   'superclassMethodCall': function(args) {

      var fn = arguments.callee.caller;

      if (fn && '$parent' in fn) {

         return Dx.Class.methods[fn.$parent].apply(this, args || []);

      } else {

         return void(0);

      }

   },

/**
 * Overridden method caller for all Dx subclasses
 * @this {Object} instance of Dx Class
 * @return {*} returned value from superclass method call.
 */
   'overrideMethodCall': function(args) {

      var fn = arguments.callee.caller;

      if (fn && '$overridden' in fn) {

         return Dx.Class.methods[fn.$overridden].apply(this, args || []);

      } else {

         return void(0);

      }

   },

/**
 * Basic Dx destructor
 * @this {Object} instance of Dx Class
 * @param {Object} operation workflow operation object used by "destroy" action.
 */
   'baseDestroyMethodCall': function(operation) {

      this.__destruct();

      Dx.clearObject(this);

      this.destroyed = true;

   },

/**
 * Basic Dx destructor
 * @this {Object} instance of Dx Class
 * @param {Object} operation workflow operation object used by "destroy" action.
 */
   'baseValidateDestroyMethodCall': function(operation) {

      if (this.destroying || this.destroyed) {

         operation.stop = true;

      } else {

         this.destroying = true;

      }

   }

};

/**
 * checks if methodName belongs to o Object as its method
 * @param {Object} o the object to inspect
 * @param {String} methodName the method name to find
 * @return {Boolean} true if methodName is a method of o, else returns false.
 */


////////////////////////////////////////////////////////////////////////
// Helpers: actions
////////////////////////////////////////////////////////////////////////

/**
 * actions helpers
 */
Dx.Class.actions = {

/**
 * actions workflow signature property found in all action workflow methods
 */
   'signatureAccess': '@action',

/**
 * iterate action definitions and register action definition object from it.
 * @this {Object} class declaration defined by Dx.Class
 * @param {String} name defined action name
 * @param {*} workflows from action definition. (only processes {Array})
 * @param {Object} o defined actions from class declaration
 */
   '_callback_eachPrepareActions': function(name, workflows, o) {

      var D = Dx;

      if (o.hasOwnProperty(name) && D.isArray(workflows)) {

         D.Class.actions.register(this, name, workflows);

      }

   },

/**
 * checks if actionName in o Object is an action
 *    with strict signature comparison
 * @param {String} actionName name of the action
 * @param {Object} o the prototype Object to inspect
 * @param {String} signature the action signature to compare
 * @return {Boolean} true if already has action with same signature.
 *    false if not found or not with the same signature.
 */
   'hasAction': function(actionName, o, signature) {

      var DClass = Dx.Class;

      var A = DClass.actions;

      var hash = A.signatureAccess;

      var isMethodOf = DClass.isMethodOf(actionName, o);

      var method = isMethodOf && o[actionName];

      return method &&

         hash in method && method[hash] == signature;

   },

/**
 * Registers action name and workflows for later creation of action and
 *    workflow methods
 * @param {Object} declaration class declaration defined by Dx.Class
 * @param {String} name action name
 * @param {Array} workflows an array of workflow names that will be converted
 *    to workflow method names.
 */
   'register': function(declaration, name, workflows) {

      var D = Dx;

      var actionIndex = declaration.actions;

      var workflow, l, methodNames, actionNames;

      if (!actionIndex.hasOwnProperty(name)) {

         // filter action methods
         methodNames = [];

         l = workflows.length;

         for (; l--;) {

            workflow = workflows[l];

            if (workflow && D.isString(workflow)) {

               methodNames[l] = name + '_' + workflow;

            } else {

               methodNames.splice(l, 1);

            }

         }

         // set to declaration
         actionIndex[name] = {

            name: name,

            methods: methodNames,

            signature: name + '[' + workflows.join(',') + ']',

            workflows: workflows

         };

         actionNames = declaration.actionNames;

         actionNames[actionNames.length] = name;

      }

   },

/**
 * Creates action and workflow methods to properties object if action is not
 *    a duplicate of superclass.
 * @param {Object} action the registered action object created by "register"
 * @param {Object} properties the object holding the class properties
 * @param {Object} superclass the prototype of Super Class Function
 */
   'createAction': function(action, properties, superclass) {

      var D = Dx;

      var DClass = D.Class;

      var A = DClass.actions;

      var actionName = action.name;

      var signature = action.signature;

      var c, l, method, methods;

      // check if not a duplicate action
      if (!A.hasAction(actionName, superclass, signature)) {

         methods = action.methods;

         for (c = -1, l = methods.length; l--;) {

            method = methods[l];

            // populate method if not found in superclass and properties
            if (!DClass.isMethodOf(method, superclass) &&

               !DClass.isMethodOf(method, properties)

            ) {

               properties[method] = A.createEmptyWorkflowMethod();

            }

         }

         // finally the action method
         properties[actionName] = A.createActionMethod(methods, signature);

      }

   },




/**
 * creates empty Function instance to be assigned as default action method
 * @return {Function} empty Function instance
 */
   'createEmptyWorkflowMethod': function() {

      function ACTION_DEFAULT_METHOD() {};

      return ACTION_DEFAULT_METHOD;

   },


/**
 * creates action method based on _methods workflow
 * @param {Array} _methods an array of method names as action workflow
 *    generated from "createAction"
 * @param {String} _signature hash generated from action name and workflows
 * @return {Function} the Action Function instance to be assigned to
 *    a class prototype
 */
   'createActionMethod': function(_methods, _signature) {

      var __ActionOperation__ = Dx.Class.actions.ActionOperation;

      function ACTION() {

         var _l = _methods.length;

         var _c = -1;

         var __ = new __ActionOperation__(this, arguments);

         var _args = __.params;

         for (; _l-- && !__.stop;) {

            this[_methods[++_c]].apply(this, _args);

         }

         return __.purgeAndReturn();

      };

      ACTION[Dx.Class.actions.signatureAccess] = _signature;

      ACTION.isDxSynthesized = true;

      return ACTION;

   }

};


/**
 * Action Operation Object which will be passed as argument to all workflows
 * @constructor
 * @param {Object} returnValue "this" instance of the workflow method
 * @param {Array} args arguments passed from workflow call
 */
Dx.Class.actions.ActionOperation = function(returnValue, args) {

   var params = [this];

   params.push.apply(params, args || []);

   this.returnValue = returnValue;

   this.params = params;

   this.stop = false;

};

/**
 * Destroys the operation object and returns the "returnValue" property
 * @return {*} last value assigned after calling all workflows
 */
Dx.Class.actions.ActionOperation.prototype = {

   'purgeAndReturn': function() {

      var returnValue = this.returnValue;

      var params = this.params;

      params.splice(0, params.length);

      Dx.clearObject(this);

      return returnValue;

   }

};

////////////////////////////////////////////////////////////////////////
// Helpers: accessors
////////////////////////////////////////////////////////////////////////

/**
 * accessors helpers
 */
Dx.Class.accessors = {

/**
 * callback to prepare and register the defined accessors
 * @this {Object} class declaration defined by Dx.Class
 * @param {String} name acessor name
 * @param {*} defaultValue the default value to assign to the acessor property
 * @param {Object} o the list of defined accessors
 */
   '_callback_eachCreateAccessors': function(name, defaultValue, o) {

      var names;

      if (o.hasOwnProperty(name)) {

         Dx.Class.accessors.createActions(this, name, defaultValue);

         names = this.accessorNames;

         names[names.length] = name;

         this.accessors[name] = defaultValue;

      }

   },

/**
 * Creates accessor actions by populating get/set methods and
 *    its workflow protected methods.
 * @param {Object} declaration class declaration defined by Dx.Class
 * @param {String} name accessor name
 * @param {*} defaultValue accessor property default value
 */
   'createActions': function(declaration, name, defaultValue) {

      var D = Dx;

      var DClass = D.Class;

      var A = DClass.actions;

      var Acc = DClass.accessors;

      var capName = name.charAt(0).toUpperCase() +

         name.substring(1, name.length);

      var superclass = D.getClass(declaration.extended).prototype;

      var properties = declaration.properties;

      var methodName;

      // create getter action
      A.register(declaration, 'get' + capName, [

         'initialize',

         'format'

      ]);

      // create getter initialize workflow method
      methodName = 'get' + capName + '_initialize';

      if (!DClass.isMethodOf(methodName, superclass) &&

         !DClass.isMethodOf(methodName, properties)

      ) {

         properties[methodName] = Acc.createGetterFormatMethod(name);

      }

      // create getter format workflow method
      methodName = 'get' + capName + '_format';

      if (!DClass.isMethodOf(methodName, superclass) &&

         !DClass.isMethodOf(methodName, properties)

      ) {

         properties[methodName] = Acc.createGetterFormatMethod(name);

      }


      // create setter action
      A.register(declaration, 'set' + capName, [

         'validate',

         'initialize',

         'process',

         'after'

      ]);

      // create setter initialize workflow method
      methodName = 'set' + capName + '_initialize';

      if (!DClass.isMethodOf(methodName, superclass) &&

         !DClass.isMethodOf(methodName, properties)

      ) {

         properties[methodName] = Acc.createSetterInitializeMethod(name);

      }

      // create setter process workflow method
      methodName = 'set' + capName + '_process';

      if (!DClass.isMethodOf(methodName, superclass) &&

         !DClass.isMethodOf(methodName, properties)

      ) {

         properties[methodName] = Acc.createSetterProcessMethod(name);

      }

   },

/**
 * Creates accessor default "get[accessor property name]_initialize" initialize
 *    method.
 * @param {String} accessorName accessor name
 * @return {Function} default accessor format method
 */
   'createGetterInitializeMethod': function(accessorName) {

      function Accessor_Get_Initialize(operation) {

         operation.returnValue = void(0);

      }

      return Accessor_Get_Initialize;

   },

/**
 * Creates accessor default "get[accessor property name]_format" format method.
 * @param {String} accessorName accessor name
 * @return {Function} default accessor format method
 */
   'createGetterFormatMethod': function(accessorName) {

      function Accessor_Get_Format(operation) {

         operation.returnValue = this[accessorName];

      }

      return Accessor_Get_Format;

   },

/**
 * Creates accessor default "set[accessor property name]_initialize"
 *    initialize method.
 * @param {String} accessorName accessor name
 * @return {Function} default accessor process method
 */
   'createSetterInitializeMethod': function(accessorName) {

      function Accessor_Set_Initialize(operation, value) {

         operation.valueToSet = value;

      }

      return Accessor_Set_Initialize;

   },

/**
 * Creates accessor default "set[accessor property name]_process"
 *    process method.
 * @param {String} accessorName accessor name
 * @return {Function} default accessor process method
 */
   'createSetterProcessMethod': function(accessorName) {

      function Accessor_Set_Process(operation) {

         this[accessorName] = operation.valueToSet;

      }

      return Accessor_Set_Process;

   }

};

////////////////////////////////////////////////////////////////////////
// Definition Processors
////////////////////////////////////////////////////////////////////////


/**
 * Process Definition: requires
 *    create declaration requirements for class
 *
 */
Dx.setClassProcessor('definition', 'requires',

   function(value, declaration) {

      var D = Dx;

      if (D.isString(value)) {

         value = [value];

      }

      if (D.isArray(value)) {

         var list = declaration.requires;

         var len = list.length;

         for (var path, c = -1, l = value.length; l--;) {

            path = value[++c];

            if (path && D.isString(path)) {

               list[len++] = path;

            }

         }

      }

   }

);

/**
 * Process Definition: extend
 *    finalize class path to extend
 */
Dx.setClassProcessor('definition', 'extend',

   function(value, declaration) {

      var D = Dx;

      var DClass = D.Class;

      var list = declaration.requires;

      if (!D.isString(value) || !value) {

         value = declaration.definition['@extend'] = DClass.baseClassName;

      }

      list[list.length] = value;

      // try discovering if Class/instance exists
      if (!DClass.isRegistered(value)) {

         DClass.discover(value);

      }

      declaration.extended = value;

   }

);

/**
 * Process Definition: actions
 *    prepare class actions
 */
Dx.setClassProcessor('definition', 'actions',

   function(value, declaration) {

      var D = Dx;

      if (!D.isObject(value)) {

         value = declaration.definition['@actions'] = {};

      }

      declaration.actionNames = [];

      declaration.actions = {};

      // prepare actions
      D.each(

         value,

         D.Class.actions._callback_eachPrepareActions,

         declaration

      );

   }

);



////////////////////////////////////////////////////////////////////////
// Pre Processors
////////////////////////////////////////////////////////////////////////

Dx.setClassProcessor('pre', 'extend',

   function(value, declaration) {

      var D = Dx;

      var DClass = D.Class;

      var SuperClass = D.getClass(declaration.extended);

      var Prototype = D.createObject(SuperClass);

      var isSynthesized = Prototype.constructor.isDxSynthesized === true;

      var A, S, actions, actionNames, hasDestroyMethod, destroyWorkflow, Super;

      // finalize class prototype
      declaration.Class = Prototype;

      Super = SuperClass.prototype;

      Prototype['@superclass'] = Super === Object.prototype ? {} : Super;

      declaration.isSynthesized = isSynthesized;

      // pre-create destructor action
      if (!isSynthesized) {

         A = DClass.actions;

         S = DClass.supplement;

         actions = declaration.actions;

         actionNames = declaration.actionNames;

         destroyWorkflow = ['allow', 'cleanup'];

         // if already has destroy action, then recreate destroy action
         if (actions.hasOwnProperty('destroy')) {

            actionNames.splice(actionNames.indexOf('destroy'), 1);

            // insert workflow to new destroy action workflow
            destroyWorkflow.splice.apply(

               destroyWorkflow, [1, 0].concat(

                  actions['destroy'].workflows

               )

            );

            delete actions['destroy'];

         }

         // recreate methods as superclass method
         if (DClass.isMethodOf('destroy', Prototype)) {

            Prototype.__destruct = Prototype.destroy;

            Prototype.destroy = null;

         } else {

            Prototype.__destruct = D.createEmptyFunction();

         }

         Prototype.destroyed = false;

         Prototype.destroying = false;

         Prototype['destroy_allow'] = S.baseValidateDestroyMethodCall;

         Prototype['destroy_cleanup'] = S.baseDestroyMethodCall;

         // register new destroy action
         A.register(declaration, 'destroy', destroyWorkflow);

      }

   }

);

/**
 *  PreProcess: accessors
 */
Dx.setClassProcessor('pre', 'accessors',

   function(value, declaration) {

      var D = Dx;

      declaration.accessors = {};

      declaration.accessorNames = [];

      if (D.isObject(value)) {

         D.each(

            value,

            D.Class.accessors._callback_eachCreateAccessors,

            declaration

         );

      }

   }

);

/**
 *  PreProcess: actions
 */
Dx.setClassProcessor('pre', 'actions',

   function(value, declaration) {

      // populate methods based on action workflows
      var D = Dx;

      var A = D.Class.actions;

      var names = declaration.actionNames;

      var actions = declaration.actions;

      //var superclass = D.getClass(declaration.extended).prototype;

      var superclass = declaration.Class;

      var properties = declaration.properties;

      var c, l, action;

      for (c = -1, l = names.length; l--;) {

         // create action methods
         A.createAction(

            actions[names[++c]],

            properties,

            superclass

         );

      }

   }

);

/**
 *  PreProcess: &#64;precallback a recursive callback
 */
Dx.setClassProcessor('pre', '@precallback',

   function(value, declaration) {

      this.supplement.applyRecursiveCallback(

         declaration.path,

         'pre',

         'precallback',

         declaration.definition

      );

   }

);

/**
 *  PreProcess: precallback a callback
 */
Dx.setClassProcessor('pre', 'precallback',

   function(value, declaration) {

      if (Dx.isFunction(value)) {

         this.setCallback(

            declaration.path,

            'pre',

            value

         );

      }

   }

);


////////////////////////////////////////////////////////////////////////
// Processors
////////////////////////////////////////////////////////////////////////

/**
 *  Process: extend
 */
Dx.setClassProcessor('', 'extend',

   function(value, declaration) {

      var D = Dx;

      var DClass = D.Class;

      var S = DClass.supplement;

      var Prototype = declaration.Class;

      var properties = declaration.properties;

      var Constructor = DClass.createConstructor();

      var SuperConstructor = Prototype.constructor;

      // finalize Class constructor
      if (!declaration.isSynthesized) {

         Prototype.__construct = SuperConstructor;

         // create superclass caller
         Prototype.$super = S.superclassMethodCall;

      }

      // relocate constructor
      if (properties.hasOwnProperty('constructor')) {

         properties.__construct = properties.constructor;

         delete properties.constructor;

      }

      Prototype.constructor = Constructor;

      Constructor.prototype = Prototype;

      Constructor['@path'] = declaration.path;

      // synthesize properties
      D.each(

         properties,

         S._callback_synthesizeClassProperty,

         Prototype

      );

   }

);

/**
 *  Process: accessors
 */
Dx.setClassProcessor('', 'accessors',

   function(value, declaration) {

      var names = declaration.accessorNames;

      var defaults = declaration.accessors;

      var properties = declaration.Class;

      var c, l, name;

      for (c = -1, l = names.length; l--;) {

         name = names[++c];

         properties[name] = defaults[name];

      }

   }

);

/**
 *  Process: static
 */
Dx.setClassProcessor('', 'singleton',

   function(value, declaration) {

      var isSingleton = declaration.isSingleton = !!value;

      var Class = declaration.Class.constructor;

      declaration.instance = isSingleton ? Class() : Class;



   }

);

/**
 *  Process: &#64;callback a recursive callback
 */
Dx.setClassProcessor('', '@callback',

   function(value, declaration) {

      this.supplement.applyRecursiveCallback(

         declaration.path,

         'declared',

         'callback',

         declaration.definition

      );

   }

);

/**
 *  Process: callback a callback
 */
Dx.setClassProcessor('', 'callback',

   function(value, declaration) {

      if (Dx.isFunction(value)) {

         this.setCallback(

            declaration.path,

            'declared',

            value

         );

      }

   }

);


////////////////////////////////////////////////////////////////////////
// Post Processors
////////////////////////////////////////////////////////////////////////

/**
 *  Post Process: public
 */
Dx.setClassProcessor('post', 'public',

   function(value, declaration) {

      var exposed = declaration.exposed = value !== false;

      if (exposed) {

         this.link(declaration.path, declaration.instance);

      }

   }

);

/**
 *  Post Process: categorize
 */
Dx.setClassProcessor('post', 'category',

   function(value, declaration) {

      var D = Dx;

      // create alias
      if (D.isString(value) && value) {

         this.setAlias(value, declaration.path);

      }

   }

);


/**
 *  Process: &#64;callback a recursive callback
 */
Dx.setClassProcessor('post', '@postcallback',

   function(value, declaration) {

      this.supplement.applyRecursiveCallback(

         declaration.path,

         'declared',

         'postprocess',

         declaration.definition

      );

   }

);

/**
 *  Process: callback a callback
 */
Dx.setClassProcessor('post', 'postcallback',

   function(value, declaration) {

      if (Dx.isFunction(value)) {

         this.setCallback(

            declaration.path,

            'declared',

            value

         );

      }

   }

);



////////////////////////////////////////////////////////////////////////
// Shortcuts
////////////////////////////////////////////////////////////////////////

/**
 * overrides class properties and methods. undeclared classes
 *    may be overridden with properties argument as soon as they are declared.
 * @param {String} path the class path
 * @param {Object} properties the new overridden properties for the class
 *
 */

Dx.override = function(path, properties) {

   var D = Dx;

   var DClass = D.Class;

   var declaration, Prototype, S, callbackFn;

   if (path && D.isString(path)) {

      S = DClass.supplement;

      declaration = DClass.getDeclaration(path);

      if (declaration && declaration.declared) {

         Prototype = declaration.Class;

         if (Prototype.__construct &&

            properties.hasOwnProperty('constructor')

         ) {

            properties.__construct = properties.constructor;

            delete properties.constructor;

         }

         D.each(

            properties,

            S._callback_synthesizeOverrideProperty,

            Prototype

         );

         if (!DClass.isMethodOf('$overridden', Prototype)) {

            Prototype.$overridden = S.overrideMethodCall;

         }

      // set callback for later call
      } else {

         callbackFn = function() {

            var me = arguments.callee;

            me.$D.override(me.$override_path, me.$override_properties);

            delete me.$D;

            delete me.$override_path;

            delete me.$override_properties;

         };

         callbackFn.$D = D;

         callbackFn.$override_path = path;

         callbackFn.$override_properties = properties;

         D.onDeclare(path, callbackFn);

      }

   }

};

/**
 * Executes callback function as soon as class in path is declared. This will
 *    directly execute the callback in case class from the
 *    given path is declared.
 *
 * @param {String} path the class path
 * @param {Function} callback the callback function to execute when declared.
 * @return {Boolean} true if callback is set or already executedm false if not.
 */
Dx.onDeclare = function(path, callback) {

   var D = Dx;

   var DClass = D.Class;

   var Fn, declareObject;

   if (D.isFunction(callback) && D.isString(path)) {

      DClass.setCallback(path, 'declared', callback);

      // just directly apply callbacks
      if (DClass.isDeclared(path)) {

         declareObject = DClass.getDeclaration(path);

         DClass.callCallbacks(

            declareObject.path,

            'declared',

            declareObject.path,

            declareObject.instance,

            declareObject.Class

         );

      }

      return true;

   }

   return false;

};
